package com.example.boot1;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

/**
 * 1.队列
 *
 * 2.阻塞队列
 *  2.1 阻塞队列有没有好处
 *  2.2 不得不阻塞，你如何管理
 */
public class BlockingQueueDemo {
    public static void main(String[] args) throws Exception{
        //testBlockingQueue抛异常()

        //testBlockingQueue特殊值温和型();

        //testBlockingQueue阻塞慎用();

        //testBlockingQueue温柔式阻塞();

        //同步队列
        testBlockingQueue不存储型();

    }
    public static void testBlockingQueue抛异常(){
        //List list  =new ArrayList<>();

        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));

        //在加第四个就会抛出异常
        // System.out.println(blockingQueue.add("x"));

        //检查队列队列首元素是多少
        System.out.println("队列首元素："+blockingQueue.element());

        //先进先出
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());

        //在删除第四个就会抛出异常
        //System.out.println(blockingQueue.remove());

        //检查队列是不是空，或者队列首元素是多少 ，如果队列移除了元素之后也会抛异常
        //System.out.println("队列首元素："+blockingQueue.element());

    }
    public static void testBlockingQueue特殊值温和型(){
        BlockingQueue<String> blockingQueue= new ArrayBlockingQueue<>(3);
        //插入成功 true
        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));
        //插入失败 false
        //System.out.println(blockingQueue.offer("x"));

        //队列的首元素
        System.out.println("队列首元素："+blockingQueue.peek());

        //取出 先进先出
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());

        //没有元素，取出时为null
        //System.out.println(blockingQueue.poll());

        //当队列取完之后在去检查首元素时：为null
        //System.out.println(blockingQueue.peek());

    }
    public static void testBlockingQueue阻塞慎用() throws Exception{
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
        blockingQueue.put("a");
        blockingQueue.put("b");
        blockingQueue.put("c");
        System.out.println("==========================");
        // 当满时往进在插入就阻塞着，不会执行之后代码
        //blockingQueue.put("x");


        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());

        //当空时在取就阻塞着
        System.out.println(blockingQueue.take());



    }
    public static void testBlockingQueue温柔式阻塞() throws Exception{
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
        //过时不候 直接加入 输出true
        System.out.println(blockingQueue.offer("a",2, TimeUnit.SECONDS));
        System.out.println(blockingQueue.offer("b",2,TimeUnit.SECONDS));
        System.out.println(blockingQueue.offer("c",2,TimeUnit.SECONDS));

        //2秒过后 输出false
        //System.out.println(blockingQueue.offer("x",2,TimeUnit.SECONDS));

        //取 直接取不等2秒
        System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));
        System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));
        System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));

        //取 等两秒 输出 null
        System.out.println(blockingQueue.poll(2,TimeUnit.SECONDS));



    }
    public static void testBlockingQueue不存储型() throws  Exception{
        BlockingQueue<String> blockingQueue = new SynchronousQueue<>();

        new Thread(() -> {
           try {
               System.out.println(Thread.currentThread().getName()+"\t put 1");
               blockingQueue.put("1");
               System.out.println(Thread.currentThread().getName()+"\t put 2");
               blockingQueue.put("2");
               System.out.println(Thread.currentThread().getName()+"\t put 3");
               blockingQueue.put("3");
           } catch (InterruptedException e) {
               throw new RuntimeException(e);
           }
       }, "AAA").start();

        new Thread(() -> {
            try {
                try{ TimeUnit.SECONDS.sleep(5);} catch(Exception e){e.printStackTrace();}
                System.out.println(Thread.currentThread().getName()+"\t"+blockingQueue.take());

                try{ TimeUnit.SECONDS.sleep(5);} catch(Exception e){e.printStackTrace();}
                System.out.println(Thread.currentThread().getName()+"\t"+blockingQueue.take());

                try{ TimeUnit.SECONDS.sleep(5);} catch(Exception e){e.printStackTrace();}
                System.out.println(Thread.currentThread().getName()+"\t"+blockingQueue.take());
            }catch (Exception e){
                e.printStackTrace();
            }
        }, "BBB").start();

    }
}
